package controller;

import java.sql.Timestamp;
import java.util.ArrayList;

import persistencia.HistoricMapper;
import persistencia.LineMapper;
import persistencia.PlanMapper;
import persistencia.ServiceMapper;
import persistencia.UserMapper;
import ui.BillView;

import customexceptions.LineAlreadyExistsException;
import customexceptions.LineNotExistsException;
import customexceptions.PlanAlreadyExistsException;
import customexceptions.PlanNotExistsException;
import customexceptions.ServiceAlreadyExistsException;
import customexceptions.ServiceNotExistsException;
import customexceptions.ServiceNotExistsInPlanException;
import customexceptions.UserAlreadyExistsException;
import customexceptions.UserNotExistsException;

import dto.LineBillDTO;
import dto.LineDTO;
import dto.PlanDTO;
import dto.ServiceDTO;
import dto.UserDTO;

import model.AdditionalLine;
import model.Line;
import model.Plan;
import model.PlanItem;
import model.Service;
import model.TitularLine;
import model.User;

//
//
//  Generated by StarUML(tm) Java Add-In
//
//  @ Project : @TPOAI
//  @ File Name : MobilePlanSellAndBillSystem.java
//  @ Date : 27/09/2012
//  @ Author : @jtabaresplebani
//
//




public class MobilePlanSellAndBillSystem {
	private ArrayList<Plan> prePaidPlans;
	private ArrayList<Plan> titularPaidPlans;
	private ArrayList<Plan> additionalPlan;
	//private ArrayList<ComunicationInterface> comunicationInterfaces;
	private ArrayList<User> users;
	private ArrayList<Line> titularLines;
	private ArrayList<Line> additionalLines;
	private ArrayList<Service> services;
	
	public MobilePlanSellAndBillSystem() {
		prePaidPlans= new ArrayList<Plan>();
		titularPaidPlans= new ArrayList<Plan>() ;
		additionalPlan= new ArrayList<Plan>() ;
		users= new ArrayList<User>() ;
		titularLines= new ArrayList<Line>() ;
		additionalLines= new ArrayList<Line>() ;
		services= new ArrayList<Service>() ;
		services = ServiceMapper.GetInstancia().LoadAllServices();
		
		for (Plan plan:PlanMapper.GetInstancia().GetAllPlans()){
			plan.populatePlanItems(PlanMapper.GetInstancia().LoadPlanItems(plan.getPlanNumber(), 
					services));
			if (plan.getIsPrepaidPlan()){
					prePaidPlans.add(plan);
			}else{
				if (plan.getIsAdditionalPlan()){
					additionalPlan.add(plan);
				} else{
					titularPaidPlans.add(plan);
				}
			}
		}
	}

	public void createTitularLine(String userDni,  String lineNumber) 
		throws LineAlreadyExistsException, UserNotExistsException {
		User user = searchUser(userDni);
		try {
			try {
				searchTitularLine(lineNumber);
			} catch (PlanNotExistsException e) {
				throw new LineAlreadyExistsException("Line "+lineNumber+" already exist for " +
						"user "+userDni);
			}
			throw new LineAlreadyExistsException("Line "+lineNumber+" already exist for " +
					"user "+userDni);
		} catch (LineNotExistsException e) {
			Line line = new TitularLine(user, lineNumber);	
			titularLines.add(line);
		}
	}
	
	public void createAdditionalLine(String titularLine,String additionalLine, String additionalUserName, 
			int planNumber) throws LineNotExistsException, 
									PlanNotExistsException, 
									LineAlreadyExistsException, 
									UserNotExistsException {
		TitularLine  line  = searchTitularLine(titularLine);
		Plan plan = searchAdditionalPlan(planNumber);
		addAditionalLine(line.getUser(),line,  additionalLine, additionalUserName, plan);
		
	}
	private void addAditionalLine(String userDni, TitularLine line, String additionalLineNumber, 
			String additionalUserName, Plan plan )
			throws LineAlreadyExistsException, UserNotExistsException{
			
			User user = searchUser(userDni);
			try {
				AdditionalLine additionalLine =  searchAdditionalLine(additionalLineNumber);
				throw new LineAlreadyExistsException("Additional Line ["+additionalLineNumber
						+"] Already Exists");
			} catch (LineNotExistsException e) {
				
					line.addAditionalLine(new AdditionalLine(plan, user, line, additionalUserName,additionalLineNumber) );
			} catch (PlanNotExistsException e) {
				throw new LineAlreadyExistsException("Additional Line ["+additionalLineNumber
						+"] Already Exists");
			}

		
	}

	public void addItemToTitularPlan( int planNumber,  String serviceName,  
			float serviceUnitCost,  int serviceFreeUnits) 
					throws PlanNotExistsException, 
							ServiceAlreadyExistsException, 
							ServiceNotExistsException {
		Plan plan = searchTitularPlan(planNumber);
		Service service = searchService(serviceName);
		plan.addPlanItem(service, serviceUnitCost, serviceFreeUnits);
	
	}
	public void addItemToAditionalPlan( int planNumber,  String serviceName,  
			float serviceUnitCost,  int serviceFreeUnits) 
					throws PlanNotExistsException, 
					ServiceAlreadyExistsException, 
					ServiceNotExistsException {
		Plan plan = searchAdditionalPlan(planNumber);
		Service service = searchService(serviceName);
		plan.addPlanItem(service, serviceUnitCost, serviceFreeUnits);
	
	}
	public void addItemToPrePaidPlan( int planNumber,  String serviceName,  
			float serviceUnitCost,  int serviceFreeUnits) 
					throws PlanNotExistsException, 
					ServiceAlreadyExistsException, 
					ServiceNotExistsException {
		Plan plan = searchPrePaidPlan(planNumber);
		Service service = searchService(serviceName);
		plan.addPlanItem(service, serviceUnitCost, serviceFreeUnits);
	
	}
	public void createService( String serviceName,  String  serviceUnits) 
			throws ServiceAlreadyExistsException {
		Service service;
		
		try{
			service = searchService(serviceName);
			throw new ServiceAlreadyExistsException("service Already Exists");
			
		} catch (ServiceNotExistsException e){
			service = new Service(serviceName, serviceUnits);
			services.add(service);
			
		}
	
	}
	private Service searchService(String serviceName) throws ServiceNotExistsException {
		for (Service service : services) {
			if (service.getServiceName().equalsIgnoreCase(serviceName))
				return service;
		}
		Service  service = ServiceMapper.GetInstancia().BuscarService(serviceName);
		if (service!=null)
		{
			services.add(service);
			return  service;
		}
		throw new ServiceNotExistsException("Service not Exists");
	}

	public void createUser( String nombre,  String  apellido,  String  dni,  
			String  domicilio,  String  telefono, String email) throws UserAlreadyExistsException {
		User user;
		
		try{
			user = searchUser(dni);
			throw new UserAlreadyExistsException("user Already Exists");
			
		} catch (UserNotExistsException e){
			if (email.length() == 0) 
				email = null;
			user = new User(nombre, apellido, dni, domicilio, email);
			users.add(user);
			
		}
	
	}

	private Line searchLine(String userDni, String lineNumber) 
			throws UserNotExistsException, LineNotExistsException {
			try {
				User user = searchUser(userDni);
				return user.searchLine(lineNumber);
			} catch (UserNotExistsException e) {
				throw new UserNotExistsException("User ["+userDni+"] not exists");
			}
	}

	private User searchUser(String dni) throws UserNotExistsException{
		for (User user : users) {
			if (user.getDni().equalsIgnoreCase(dni))
				return user;
		}
		User  user = UserMapper.GetInstancia().BuscarUser(dni);
		if (user!=null)
		{
			users.add(user);
			return  user;
		}
		throw new UserNotExistsException("User not Exists");
	}
	public void associateLineToUser(String lineNumber, String userDni) {
	
	}
	
	public ArrayList<LineBillDTO> invoiceLines() {
			ArrayList<LineBillDTO>  bills =  new ArrayList<LineBillDTO>();
			ArrayList<TitularLine> lines = LineMapper.GetInstancia().loadTitularLine();
			for (Line line : lines) {
					LineBillDTO bill = line.invoice();
					if (bill!=null){
						bills.add(bill);
					}
			}
			return bills;
	}
	
	public void changeTitularLinePlan(String lineNumber, int  planNumber) 
			throws LineNotExistsException, PlanNotExistsException, UserNotExistsException {
			Line line = searchTitularLine(lineNumber);
			Plan plan = searchTitularPlan(planNumber);
			line.setPlan(plan);
	}
	public void changeAdditionalLinePlan(String lineNumber, int  planNumber) 
			throws LineNotExistsException, PlanNotExistsException, UserNotExistsException {
			Line line = searchAdditionalLine(lineNumber);
			Plan plan = searchAdditionalPlan(planNumber);
			line.setPlan(plan);
	}	
	public UserDTO searchUserData(String dni) throws UserNotExistsException {
		User user = searchUser(dni);
		return user.getDTO();
	}
	public ArrayList<UserDTO> getUsers() {
		ArrayList<UserDTO> usersDto = new ArrayList<UserDTO>();
		for(User user:UserMapper.GetInstancia().LoadAllUsers()){
			usersDto.add(user.getDTO());
		}
		return usersDto;
		
	}	
	public UserDTO getUser(String dni) throws UserNotExistsException{
		User user = searchUser(dni);
		return user.getDTO();
	}
	private Plan searchTitularPlan(int  planNumber) throws PlanNotExistsException {
		for (Plan plan : titularPaidPlans ) {
			if (plan.getPlanNumber()==(planNumber))
				return plan;
		}
		throw new PlanNotExistsException("Plan not Exists");	
	}
	private Plan searchAdditionalPlan(int planNumber) throws PlanNotExistsException {
		for (Plan plan : additionalPlan ) {
			if (plan.getPlanNumber()==(planNumber))
				return plan;
		}
		throw new PlanNotExistsException("Plan not Exists");	
	}	
	private Plan searchPrePaidPlan(int planNumber) throws PlanNotExistsException {
		for (Plan plan : prePaidPlans ) {
			if (plan.getPlanNumber()==(planNumber))
				return plan;
		}
		throw new PlanNotExistsException("Plan not Exists");	
	}	
	public ArrayList<PlanDTO> getPlans() {
		ArrayList<PlanDTO> plansDTO =  new ArrayList<PlanDTO>();
		plansDTO.addAll(getTitularPlans());
		plansDTO.addAll(getAdditionalPlans());
		plansDTO.addAll(getPrepaidPlans());

		return plansDTO;	
	}
	public ArrayList<PlanDTO> getTitularPlans() {
		
		ArrayList<PlanDTO> plansDTO =  new ArrayList<PlanDTO>();
		for (Plan plan : titularPaidPlans) {
			plansDTO.add(plan.getDTO());
		}
		return plansDTO;	
	}
	public ArrayList<PlanDTO> getAdditionalPlans() {
		ArrayList<PlanDTO> plansDTO =  new ArrayList<PlanDTO>();
		for (Plan plan : additionalPlan) {
			plansDTO.add(plan.getDTO());
		}
		return plansDTO;	
	}
	public ArrayList<PlanDTO> getPrepaidPlans() {
		ArrayList<PlanDTO> plansDTO =  new ArrayList<PlanDTO>();
		for (Plan plan : prePaidPlans) {
			plansDTO.add(plan.getDTO());
		}
		
		return plansDTO;	
	}
	public PlanDTO getPlan(int planNumber) throws PlanNotExistsException {
		Plan plan;
		try {
			 plan =  searchAdditionalPlan(planNumber);
		} catch (PlanNotExistsException e) {
			try {
				 plan = searchAdditionalPlan(planNumber);
				
			} catch (PlanNotExistsException e1) {
				 plan = searchPrePaidPlan(planNumber);
			}
		}
		return plan.getDTO();
	
	}
	
	private TitularLine searchTitularLine(String lineNumber) throws LineNotExistsException, 
	UserNotExistsException, PlanNotExistsException{
		for (Line line : titularLines ) {
			if (line.getLineNumber().equalsIgnoreCase(lineNumber))
				return (TitularLine) line;
		}
		TitularLine  line = LineMapper.GetInstancia().BuscarTitularLine(lineNumber);
		if (line!=null)
		{
			int linePlan =LineMapper.GetInstancia().BuscarTitularLinePlan(lineNumber);
			String lineUser = LineMapper.GetInstancia().BuscarTitularLineUserId(lineNumber);
			User user = searchUser(lineUser);
			try {
				Plan plan = searchTitularPlan(linePlan);
				line.setPlan(plan);
			} catch (PlanNotExistsException e) {
				try {
					Plan plan = searchPrePaidPlan(linePlan);
					line.setPlan(plan);
				} catch (PlanNotExistsException e1) {
					throw new PlanNotExistsException("plan not exist");
				}
			}
			line.populateUser(user);
			titularLines.add(line);
			return  line;
		}
		throw new LineNotExistsException("Line not Exists");		
	}
	
	private AdditionalLine searchAdditionalLine(String lineNumber) throws LineNotExistsException, 
	PlanNotExistsException, UserNotExistsException {
		for (Line line : additionalLines ) {
			if (line.getLineNumber().equalsIgnoreCase(lineNumber))
				return (AdditionalLine) line;
		}
		AdditionalLine  line = LineMapper.GetInstancia().BuscarAdditionalLine(lineNumber);
		if (line!=null)
		{
			String parentLine = LineMapper.GetInstancia().BuscarAdditionalLineParentLine(lineNumber);
			int linePlan = LineMapper.GetInstancia().BuscarAdditionalLinePlan(lineNumber);
			TitularLine lineParent =  searchTitularLine(parentLine);
			Plan plan =  searchAdditionalPlan(linePlan);
			line.populatePrincipalLine(lineParent);
			line.populatePlan(plan);
			additionalLines.add(line);
			return  line;
		}
		throw new LineNotExistsException("Line not Exists");			
	}
	
	public void createPrePaidPlan(String planDescription) 
			throws PlanAlreadyExistsException {
		Plan  plan;
		
		//try{
		//	plan = searchPrePaidPlan(planNumber);
		//	throw new PlanAlreadyExistsException("plan Already Exists");
			
		//} catch (PlanNotExistsException e){
			plan = new Plan(planDescription);
			prePaidPlans.add(plan);
		//}
		
	}

	public void createTitularPlan(String planDescription, float planCost, float discount) 
			throws PlanAlreadyExistsException {
		Plan  plan;
		
		//try{
		//	plan = searchTitularPlan(planNumber);
		//	throw new PlanAlreadyExistsException("Plan Already Exists");
			
		//} catch (PlanNotExistsException e){
			plan = new Plan(discount, planCost, planDescription);
			titularPaidPlans.add(plan);			
		//}	
	}

	public void createAdditionalPlan(String planDescription, float planCost, float discount) 
			throws PlanAlreadyExistsException {
	Plan  plan;	
//		try{
//			plan = searchAdditionalPlan (planNumber);
//			throw new PlanAlreadyExistsException("Plan Already Exists");
//			
//		} catch (PlanNotExistsException e){
			plan = new Plan(discount, planCost, planDescription,true);
			additionalPlan.add(plan);			
//		}	
	}
	public void useLine(String lineNumber, String serviceName, int useUnits) 
			throws LineNotExistsException, ServiceNotExistsException, 
			ServiceNotExistsInPlanException, UserNotExistsException, PlanNotExistsException{
		Line line;
		Service service;
		try {
			line = searchTitularLine(lineNumber);
		} catch (LineNotExistsException e) {
			line = searchAdditionalLine(lineNumber);
		}
		service = searchService(serviceName);
		line.useLine(service, useUnits);
		
	}

	public LineDTO getLine(String lineNumber) throws LineNotExistsException, 
		UserNotExistsException, PlanNotExistsException {
		Line line;
		try {
			line = searchTitularLine(lineNumber);
			return line.getDTO();
		} catch (LineNotExistsException e) {
				line = searchAdditionalLine(lineNumber);
		}
		return line.getDTO();
	}

	public ArrayList<ServiceDTO> getServices() {
		ArrayList<ServiceDTO> servicesDTO =  new ArrayList<ServiceDTO>();
		for (Service service : services) {
			servicesDTO.add(service.getDTO());
		}
		return servicesDTO;
	}
	public ArrayList<LineBillDTO> getHistoricPerPeriod(Timestamp from, Timestamp to){
		ArrayList<LineBillDTO> historics = HistoricMapper.GetInstancia().getHistoricPerPeriod(from, to) ;
		return historics;
		
	}

}
